﻿using System;
using System.Collections.Generic;
using System.Data.Entity.Core.Metadata.Edm;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using WorldBankBBS.Common;

namespace WorldBankBBS.Comms
{
    public class TcpCommunicator : ITcpConnection
    {
        private readonly TcpClient _client = null;
        private int _waitingBytes;
        private Socket _tcpSocket;
        private bool _isConnected;

        public TcpCommunicator(TcpClient client)
        {
            _client = client;
            if (client.Client.RemoteEndPoint != null)
            {
                ClientAddress = ((IPEndPoint) client.Client.RemoteEndPoint).Address;
            }
        }

        public ISession Session { get; set; }

        public int SendData(byte[] data)
        {
            return SendData(data, 0, data.Length, 1);
        }

        public int SendData(byte[] data, int chunksize)
        {
            return SendData(data, 0, data.Length, chunksize);
        }

        public int SendData(byte[] data, int offset, int bytes)
        {
            return SendData(data, offset, bytes, 1);
        }

        public int SendData(byte[] data, int offset, int bytes, int chunkSize)
        {
            int result = 0;
            int i = 0;
            bytes = Math.Min(data.Length, bytes);
            for (; i < bytes; i += chunkSize)
            {
                _client.Client.Send(data, offset + i, chunkSize, SocketFlags.None);

                if (HasData)
                {
                    var buffer = new byte[_client.Client.Available];
                    _client.Client.Receive(buffer);
                    if (buffer[0] == 1) return i;
                    if (buffer[0] == 3)
                    {
                        //if (Pause != null)
                        //{
                        //    if (Pause(Session)) return i;
                        //}
                    }
                }
            }

            if(i > 0)
                _client.Client.Send(data, i - chunkSize, bytes - i, SocketFlags.None);

            result = bytes;

            return result;
        }

        public bool HasData
        {
            get { return _client.Client.Available > 0; }
            private set {  }
        }

        public int WaitingBytes
        {
            get { return _client.Client.Available; }
            private set {  }
        }

        public bool IsConnected
        {
            get { return _client.Connected; }
        }

        public int ReadData(byte[] data, int offset, int bytes)
        {
            int result = 0;

            if (HasData)
            {
                if (_client.Client.Available <= bytes)
                {
                    result = _client.Client.Receive(data, offset, _client.Available, SocketFlags.None);
                }
                else
                {
                    result = _client.Client.Receive(data, offset, bytes, SocketFlags.None);
                }
            }

            return result;
        }

        public int ReadData(byte[] data)
        {
            return ReadData(data, 0, data.Length);
        }

        public void Terminate()
        {
            _client.Client.Close();
        }

        public IPAddress ClientAddress { get; set; }

        public TcpClient TcpSocket
        {
            get { return _client; }
            set { }
        }

        public void Clear()
        {
            while (WaitingBytes > 0)
            {
                var count = WaitingBytes;
                var bytes = new byte[count];
                _client.Client.Receive(bytes, 0, count, SocketFlags.None);
            }
        }
    }
}
